package cn.lili.modules.payment.kit.plugin.wechat;

import cn.hutool.core.net.URLDecoder;
import cn.hutool.core.net.URLEncoder;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.lili.cache.Cache;
import cn.lili.cache.CachePrefix;
import cn.lili.common.enums.DictCodeEnum;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.enums.ResultUtil;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.properties.ApiProperties;
import cn.lili.common.security.context.UserContext;
import cn.lili.common.utils.*;
import cn.lili.common.vo.ResultMessage;
import cn.lili.modules.connect.entity.Connect;
import cn.lili.modules.connect.entity.enums.ConnectEnum;
import cn.lili.modules.connect.service.ConnectService;
import cn.lili.modules.dict.entity.vos.SysDictItemVO;
import cn.lili.modules.member.entity.dos.*;
import cn.lili.modules.member.entity.dto.ConnectQueryDTO;
import cn.lili.modules.member.entity.enums.PartnerStatusEnum;
import cn.lili.modules.member.entity.vo.GradeVO;
import cn.lili.modules.member.entity.vo.MemberVO;
import cn.lili.modules.member.mapper.GradeLevelMapper;
import cn.lili.modules.member.mapper.GradeMapper;
import cn.lili.modules.member.mapper.MemberMapper;
import cn.lili.modules.member.mapper.PartnerMapper;
import cn.lili.modules.member.service.EextensionService;
import cn.lili.modules.member.service.MemberService;
import cn.lili.modules.member.service.PartnerService;
import cn.lili.modules.message.entity.dos.RollMessage;
import cn.lili.modules.message.mapper.RollMessageMapper;
import cn.lili.modules.member.service.RechargeFowService;
import cn.lili.modules.order.order.entity.dos.Order;
import cn.lili.modules.order.order.entity.dos.OrderItem;
import cn.lili.modules.order.order.entity.enums.DeliverStatusEnum;
import cn.lili.modules.order.order.entity.enums.PayStatusEnum;
import cn.lili.modules.order.order.service.OrderItemService;
import cn.lili.modules.order.order.service.OrderService;
import cn.lili.modules.payment.entity.RefundLog;
import cn.lili.modules.payment.entity.enums.CashierEnum;
import cn.lili.modules.payment.entity.enums.PaymentMethodEnum;
import cn.lili.modules.payment.kit.CashierSupport;
import cn.lili.modules.payment.kit.Payment;
import cn.lili.modules.payment.kit.core.PaymentHttpResponse;
import cn.lili.modules.payment.kit.core.enums.RequestMethodEnums;
import cn.lili.modules.payment.kit.core.enums.SignType;
import cn.lili.modules.payment.kit.core.kit.*;
import cn.lili.modules.payment.kit.core.utils.DateTimeZoneUtil;
import cn.lili.modules.payment.kit.dto.PayParam;
import cn.lili.modules.payment.kit.dto.PaymentSuccessParams;
import cn.lili.modules.payment.kit.params.dto.CashierParam;
import cn.lili.modules.payment.kit.plugin.wechat.enums.WechatApiEnum;
import cn.lili.modules.payment.kit.plugin.wechat.enums.WechatDomain;
import cn.lili.modules.payment.kit.plugin.wechat.model.*;
import cn.lili.modules.payment.service.PaymentService;
import cn.lili.modules.payment.service.RefundLogService;
import cn.lili.modules.permission.entity.dos.Role;
import cn.lili.modules.permission.mapper.RoleMapper;
import cn.lili.modules.store.entity.dos.Store;
import cn.lili.modules.store.entity.vos.StoreDetailVO;
import cn.lili.modules.store.mapper.StoreDetailMapper;
import cn.lili.modules.store.mapper.StoreMapper;
import cn.lili.modules.store.service.StoreService;
import cn.lili.modules.system.entity.dos.Region;
import cn.lili.modules.system.entity.dos.Setting;
import cn.lili.modules.system.entity.dto.payment.WechatPaymentSetting;
import cn.lili.modules.system.entity.enums.SettingEnum;
import cn.lili.modules.system.mapper.RegionMapper;
import cn.lili.modules.system.service.SettingService;
import cn.lili.modules.wallet.entity.dos.MemberWallet;
import cn.lili.modules.wallet.entity.dos.Recharge;
import cn.lili.modules.wallet.entity.enums.DepositServiceTypeEnum;
import cn.lili.modules.wallet.entity.enums.WalletOwnerEnum;
import cn.lili.modules.wallet.service.MemberWalletService;
import cn.lili.modules.wallet.service.RechargeService;
import cn.lili.modules.whitebar.mapper.CommissionMapper;
import cn.lili.modules.whitebar.mapper.RateSettingMapper;
import cn.lili.modules.whitebar.service.RateSettingService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.cert.X509Certificate;
import java.util.*;

/**
 * 微信支付
 *
 * @author Chopper
 * @since 2020/12/21 17:44
 */
@Slf4j
@Component
public class WechatPlugin implements Payment {

	/**
	 * 收银台
	 */
	@Autowired
	private CashierSupport cashierSupport;
	/**
	 * 支付日志
	 */
	@Autowired
	private PaymentService paymentService;
	/**
	 * 缓存
	 */
	@Autowired
	private Cache<String> cache;
	/**
	 * 退款日志
	 */
	@Autowired
	private RefundLogService refundLogService;
	/**
	 * API域名
	 */
	@Autowired
	private ApiProperties apiProperties;
	/**
	 * 配置
	 */
	@Autowired
	private SettingService settingService;
	/**
	 * 联合登陆
	 */
	@Autowired
	private ConnectService connectService;
	/**
	 * 联合登陆
	 */
	@Autowired
	private OrderService orderService;

	@Autowired
	private OrderItemService orderItemService;

	@Autowired
	private RechargeService rechargeService;

	@Autowired
	private MemberWalletService memberWalletService;

	@Autowired
	private GradeMapper gradeMapper;

	@Autowired
	private EextensionService eextensionService;

	@Autowired
	private RateSettingMapper rateSettingMapper;

	@Autowired
	private MemberService memberService;
	@Autowired
	private MemberMapper memberMapper;

	@Autowired
	private PartnerMapper partnerMapper;

	@Autowired
	private RateSettingService rateSettingService;

	@Autowired
	private PartnerService partnerService;

	@Autowired
	private StoreService storeService;

	@Autowired
	private CommissionMapper commissionMapper;

	@Autowired
	private GradeLevelMapper gradeLevelMapper;

	@Autowired
	private StoreDetailMapper storeDetailMapper;

	@Autowired
	private StoreMapper storeMapper;

	@Autowired
	private RegionMapper regionMapper;
	@Autowired
	private RoleMapper roleMapper;

	@Autowired
	private RollMessageMapper rollMessageMapper;

	@Autowired
	private RechargeFowService rechargeFowService;

	@Override
	public ResultMessage<Object> h5pay(HttpServletRequest request, HttpServletResponse response1, PayParam payParam) {

		try {
			CashierParam cashierParam = cashierSupport.cashierParam(payParam);

			// 支付参数准备
			SceneInfo sceneInfo = new SceneInfo();
			sceneInfo.setPayer_client_ip(IpKit.getRealIp(request));
			H5Info h5Info = new H5Info();
			h5Info.setType("WAP");
			sceneInfo.setH5_info(h5Info);

			// 支付金额
			Integer fen = CurrencyUtil.fen(cashierParam.getPrice());
			// 第三方付款订单
			String outOrderNo = SnowFlake.getIdStr();
			// 过期时间
			String timeExpire = DateTimeZoneUtil.dateToTimeZone(System.currentTimeMillis() + 1000 * 60 * 10);

			// 回传数据
			String attach = URLEncoder.createDefault().encode(JSONUtil.toJsonStr(payParam), StandardCharsets.UTF_8);

			WechatPaymentSetting setting = wechatPaymentSetting();
			String appid = setting.getServiceAppId();
			if (appid == null) {
				throw new ServiceException(ResultCode.WECHAT_PAYMENT_NOT_SETTING);
			}
			UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel().setAppid(appid).setMchid(setting.getMchId())
					.setDescription(cashierParam.getDetail()).setOut_trade_no(outOrderNo).setTime_expire(timeExpire)
					.setAttach(attach).setNotify_url(notifyUrl(apiProperties.getBuyer(), PaymentMethodEnum.WECHAT))
					.setAmount(new Amount().setTotal(fen)).setScene_info(sceneInfo);

			log.info("统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel));
			PaymentHttpResponse response = WechatApi.v3(RequestMethodEnums.POST, WechatDomain.CHINA.toString(),
					WechatApiEnum.H5_PAY.toString(), setting.getMchId(), setting.getSerialNumber(), null,
					setting.getApiclient_key(), JSONUtil.toJsonStr(unifiedOrderModel));

			return ResultUtil.data(JSONUtil.toJsonStr(response.getBody()));
		} catch (Exception e) {
			log.error("微信H5支付错误", e);
			throw new ServiceException(ResultCode.PAY_ERROR);
		}
	}

	@Override
	public ResultMessage<Object> jsApiPay(HttpServletRequest request, PayParam payParam) {

		try {
			Connect connect = connectService.queryConnect(ConnectQueryDTO.builder()
					.userId(UserContext.getCurrentUser().getId()).unionType(ConnectEnum.WECHAT.name()).build());
			if (connect == null) {
				return null;
			}

			Payer payer = new Payer();
			payer.setOpenid(connect.getUnionId());

			CashierParam cashierParam = cashierSupport.cashierParam(payParam);

			// 支付金额
			Integer fen = CurrencyUtil.fen(cashierParam.getPrice());
			// 第三方付款订单
			String outOrderNo = SnowFlake.getIdStr();
			// 过期时间
			String timeExpire = DateTimeZoneUtil.dateToTimeZone(System.currentTimeMillis() + 1000 * 60 * 10);

			String attach = URLEncoder.createDefault().encode(JSONUtil.toJsonStr(payParam), StandardCharsets.UTF_8);

			WechatPaymentSetting setting = wechatPaymentSetting();
			String appid = setting.getServiceAppId();
			if (appid == null) {
				throw new ServiceException(ResultCode.WECHAT_PAYMENT_NOT_SETTING);
			}
			UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel().setAppid(appid).setMchid(setting.getMchId())
					.setDescription(cashierParam.getDetail()).setOut_trade_no(outOrderNo).setTime_expire(timeExpire)
					.setAttach(attach).setNotify_url(notifyUrl(apiProperties.getBuyer(), PaymentMethodEnum.WECHAT))
					.setAmount(new Amount().setTotal(fen)).setPayer(payer);

			log.info("统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel));
			PaymentHttpResponse response = WechatApi.v3(RequestMethodEnums.POST, WechatDomain.CHINA.toString(),
					WechatApiEnum.JS_API_PAY.toString(), setting.getMchId(), setting.getSerialNumber(), null,
					setting.getApiclient_key(), JSONUtil.toJsonStr(unifiedOrderModel));
			// 根据证书序列号查询对应的证书来验证签名结果
			boolean verifySignature = WxPayKit.verifySignature(response, getPlatformCert());
			log.info("verifySignature: {}", verifySignature);
			log.info("统一下单响应 {}", response);

			if (verifySignature) {
				String body = response.getBody();
				JSONObject jsonObject = JSONUtil.parseObj(body);
				String prepayId = jsonObject.getStr("prepay_id");
				Map<String, String> map = WxPayKit.jsApiCreateSign(appid, prepayId, setting.getApiclient_key());
				log.info("唤起支付参数:{}", map);

				return ResultUtil.data(map);
			}
			log.error("微信支付参数验证错误，请及时处理");
			throw new ServiceException(ResultCode.PAY_ERROR);
		} catch (Exception e) {
			log.error("支付异常", e);
			throw new ServiceException(ResultCode.PAY_ERROR);
		}
	}

	@Override
	public ResultMessage<Object> appPay(HttpServletRequest request, PayParam payParam) {

		try {

			CashierParam cashierParam = cashierSupport.cashierParam(payParam);

			// 支付金额
			Integer fen = CurrencyUtil.fen(cashierParam.getPrice());
			// 第三方付款订单
			String outOrderNo = SnowFlake.getIdStr();
			// 过期时间
			String timeExpire = DateTimeZoneUtil.dateToTimeZone(System.currentTimeMillis() + 1000 * 60 * 10);

			String attach = URLEncoder.createDefault().encode(JSONUtil.toJsonStr(payParam), StandardCharsets.UTF_8);

			WechatPaymentSetting setting = wechatPaymentSetting();
			String appid = setting.getAppId();
			if (appid == null) {
				throw new ServiceException(ResultCode.WECHAT_PAYMENT_NOT_SETTING);
			}
			UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel().setAppid(appid).setMchid(setting.getMchId())
					.setDescription(cashierParam.getDetail()).setOut_trade_no(outOrderNo).setTime_expire(timeExpire)
					.setAttach(attach).setNotify_url(notifyUrl(apiProperties.getBuyer(), PaymentMethodEnum.WECHAT))
					.setAmount(new Amount().setTotal(fen));

			log.info("统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel));
			PaymentHttpResponse response = WechatApi.v3(RequestMethodEnums.POST, WechatDomain.CHINA.toString(),
					WechatApiEnum.APP_PAY.toString(), setting.getMchId(), setting.getSerialNumber(), null,
					setting.getApiclient_key(), JSONUtil.toJsonStr(unifiedOrderModel));
			// 根据证书序列号查询对应的证书来验证签名结果
			boolean verifySignature = WxPayKit.verifySignature(response, getPlatformCert());
			log.info("verifySignature: {}", verifySignature);
			log.info("统一下单响应 {}", response);

			if (verifySignature) {
				JSONObject jsonObject = JSONUtil.parseObj(response.getBody());
				String prepayId = jsonObject.getStr("prepay_id");
				Map<String, String> map = WxPayKit.appPrepayIdCreateSign(appid, setting.getMchId(), prepayId,
						setting.getApiclient_key(), SignType.HMACSHA256);
				log.info("唤起支付参数:{}", map);

				return ResultUtil.data(map);
			}
			log.error("微信支付参数验证错误，请及时处理");
			throw new ServiceException(ResultCode.PAY_ERROR);
		} catch (Exception e) {
			log.error("支付异常", e);
			throw new ServiceException(ResultCode.PAY_ERROR);
		}
	}

	@Override
	public ResultMessage<Object> nativePay(HttpServletRequest request, PayParam payParam) {

		try {

			CashierParam cashierParam = cashierSupport.cashierParam(payParam);

			// 支付金额
			Integer fen = CurrencyUtil.fen(cashierParam.getPrice());
			// 第三方付款订单
			String outOrderNo = SnowFlake.getIdStr();
			// 过期时间
			String timeExpire = DateTimeZoneUtil.dateToTimeZone(System.currentTimeMillis() + 1000 * 60 * 10);

			String attach = URLEncoder.createDefault().encode(JSONUtil.toJsonStr(payParam), StandardCharsets.UTF_8);

			WechatPaymentSetting setting = wechatPaymentSetting();

			String appid = setting.getServiceAppId();
			if (appid == null) {
				throw new ServiceException(ResultCode.WECHAT_PAYMENT_NOT_SETTING);
			}
			UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel().setAppid(appid).setMchid(setting.getMchId())
					.setDescription(cashierParam.getDetail()).setOut_trade_no(outOrderNo).setTime_expire(timeExpire)
					// 回传参数
					.setAttach(attach).setNotify_url(notifyUrl(apiProperties.getBuyer(), PaymentMethodEnum.WECHAT))
					.setAmount(new Amount().setTotal(fen));

			log.info("统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel));
			PaymentHttpResponse response = WechatApi.v3(RequestMethodEnums.POST, WechatDomain.CHINA.toString(),
					WechatApiEnum.NATIVE_PAY.toString(), setting.getMchId(), setting.getSerialNumber(), null,
					setting.getApiclient_key(), JSONUtil.toJsonStr(unifiedOrderModel));
			log.info("统一下单响应 {}", response);
			// 根据证书序列号查询对应的证书来验证签名结果
			boolean verifySignature = WxPayKit.verifySignature(response, getPlatformCert());
			log.info("verifySignature: {}", verifySignature);

			if (verifySignature) {
				return ResultUtil.data(new JSONObject(response.getBody()).getStr("code_url"));
			} else {
				log.error("微信支付参数验证错误，请及时处理");
				throw new ServiceException(ResultCode.PAY_ERROR);
			}
		} catch (ServiceException e) {
			log.error("支付异常", e);
			throw new ServiceException(ResultCode.PAY_ERROR);
		} catch (Exception e) {
			log.error("支付异常", e);
			throw new ServiceException(ResultCode.PAY_ERROR);
		}
	}

	@Override
	public ResultMessage<Object> transferPay(HttpServletRequest request, PayParam payParam) {

		try {

			CashierParam cashierParam = cashierSupport.cashierParam(payParam);

			// 支付金额
			Integer fen = CurrencyUtil.fen(cashierParam.getPrice());
			// 第三方付款订单
			String outOrderNo = SnowFlake.getIdStr();
			// 过期时间
			String timeExpire = DateTimeZoneUtil.dateToTimeZone(System.currentTimeMillis() + 1000 * 60 * 10);

			String attach = URLEncoder.createDefault().encode(JSONUtil.toJsonStr(payParam), StandardCharsets.UTF_8);

			WechatPaymentSetting setting = wechatPaymentSetting();

			String appid = setting.getServiceAppId();
			if (appid == null) {
				throw new ServiceException(ResultCode.WECHAT_PAYMENT_NOT_SETTING);
			}
			UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel().setAppid(appid).setMchid(setting.getMchId())
					.setDescription(cashierParam.getDetail()).setOut_trade_no(outOrderNo).setTime_expire(timeExpire)
					// 回传参数
					.setAttach(attach).setNotify_url(notifyUrl(apiProperties.getBuyer(), PaymentMethodEnum.WECHAT))
					.setAmount(new Amount().setTotal(fen));

			log.info("统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel));
			PaymentHttpResponse response = WechatApi.v3(RequestMethodEnums.POST, WechatDomain.CHINA.toString(),
					WechatApiEnum.NATIVE_PAY.toString(), setting.getMchId(), setting.getSerialNumber(), null,
					setting.getApiclient_key(), JSONUtil.toJsonStr(unifiedOrderModel));
			log.info("统一下单响应 {}", response);
			// 根据证书序列号查询对应的证书来验证签名结果
			boolean verifySignature = WxPayKit.verifySignature(response, getPlatformCert());
			log.info("verifySignature: {}", verifySignature);

			if (verifySignature) {
				return ResultUtil.data(new JSONObject(response.getBody()).getStr("code_url"));
			} else {
				log.error("微信支付参数验证错误，请及时处理");
				throw new ServiceException(ResultCode.PAY_ERROR);
			}
		} catch (ServiceException e) {
			log.error("支付异常", e);
			throw new ServiceException(ResultCode.PAY_ERROR);
		} catch (Exception e) {
			log.error("支付异常", e);
			throw new ServiceException(ResultCode.PAY_ERROR);
		}
	}

	@Override
	public ResultMessage<Object> mpPay(HttpServletRequest request, PayParam payParam) {

		Connect connect = new Connect();
		// if (WalletOwnerEnum.RECHARGE.name().equals(payParam.getOwner())){
		// connect = connectService.queryConnect(
		// ConnectQueryDTO.builder().userId(UserContext.getCurrentUser().getId()).unionType(ConnectEnum.WECHAT_OPEN_ID.name()).build()
		// );
		// }else {

		Object cacheData = cache.get(CachePrefix.WECHAT_SESSION_PARAMS.getPrefix() + payParam.getUuid());
		Map<String, String> cacheMap = new HashMap<>(3);
		cacheMap = (Map<String, String>) cacheData;
		if (ObjectUtil.isEmpty(cacheMap)
				|| (StringUtils.isEmpty(cacheMap.get("openId")) && StringUtils.isEmpty(cacheMap.get("unionId")))) {
			throw new ServiceException(ResultCode.USER_AUTH_EXPIRED);
		}
		connect = connectService.queryConnect(ConnectQueryDTO.builder().userId(UserContext.getCurrentUser().getId())
				.unionType(ConnectEnum.WECHAT_MP_OPEN_ID.name())
				.unionId(StringUtils.isNotEmpty(cacheMap.get("openId"))
						? cacheMap.get("openId")
						: cacheMap.get("unionId"))
				.build());
		// }
		if (connect == null) {
			throw new ServiceException(ResultCode.USER_AUTH_EXPIRED);
		}
		Payer payer = new Payer();
		payer.setOpenid(connect.getUnionId());

		CashierParam cashierParam = cashierSupport.cashierParam(payParam);

		// 支付金额
		Integer fen = CurrencyUtil.fen(cashierParam.getPrice());
		// 第三方付款订单
		String outOrderNo = SnowFlake.getIdStr();

		// 微信小程序，appid 需要单独获取，这里读取了联合登陆配置的appid ，实际场景小程序自动登录，所以这个appid是最为保险的做法
		// 如果有2开需求，这里需要调整，修改这个appid的获取途径即可
		String appid = wechatPaymentSetting().getMpAppId();
		if (appid == null) {
			throw new ServiceException(ResultCode.WECHAT_PAYMENT_NOT_SETTING);
		}
		try {
			// 过期时间
			String timeExpire = DateTimeZoneUtil.dateToTimeZone(System.currentTimeMillis() + 1000 * 60 * 10);

			PayParam payParam1 = new PayParam();
			payParam1.setClientType(payParam.getClientType());
			payParam1.setOrderType(payParam.getOrderType());
			payParam1.setSn(payParam.getSn());
			String attach = URLEncoder.createDefault().encode(JSONUtil.toJsonStr(payParam1), StandardCharsets.UTF_8);

			WechatPaymentSetting setting = wechatPaymentSetting();
			UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel().setAppid(appid).setMchid(setting.getMchId())
					.setDescription(cashierParam.getDetail()).setOut_trade_no(outOrderNo).setTime_expire(timeExpire)
					.setAttach(attach).setNotify_url(notifyUrl(apiProperties.getBuyer(), PaymentMethodEnum.WECHAT))
					.setAmount(new Amount().setTotal(fen)).setPayer(payer);

			log.info("统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel));
			PaymentHttpResponse response = WechatApi.v3(RequestMethodEnums.POST, WechatDomain.CHINA.toString(),
					WechatApiEnum.JS_API_PAY.toString(), setting.getMchId(), setting.getSerialNumber(), null,
					setting.getApiclient_key(), JSONUtil.toJsonStr(unifiedOrderModel));
			// 根据证书序列号查询对应的证书来验证签名结果
			boolean verifySignature = WxPayKit.verifySignature(response, getPlatformCert());
			log.info("verifySignature: {}", verifySignature);
			log.info("统一下单响应 {}", response);

			if (verifySignature) {
				// //钱包增加易贝
				// Recharge recharge = rechargeService.getRecharge(payParam.getSn());
				// memberWalletService.increase(new MemberWalletUpdateDTO(
				// recharge.getYiBei(),
				// recharge.getMemberId(),
				// "充值订单，余额增加[" + recharge.getYiBei() + "]",
				// DepositServiceTypeEnum.WALLET_RECHARGE.name(), payParam.getOwner()));

				String body = response.getBody();
				JSONObject jsonObject = JSONUtil.parseObj(body);
				String prepayId = jsonObject.getStr("prepay_id");
				Map<String, String> map = WxPayKit.jsApiCreateSign(appid, prepayId, setting.getApiclient_key());
				log.info("唤起支付参数:{}", map);

				return ResultUtil.data(map);
			}
			log.error("微信支付参数验证错误，请及时处理");
			throw new ServiceException(ResultCode.PAY_ERROR);
		} catch (Exception e) {
			log.error("支付异常", e);
			throw new ServiceException(ResultCode.PAY_ERROR);
		}

	}

	@Override
	public void callBack(HttpServletRequest request) {
		try {
			verifyNotify(request);
		} catch (Exception e) {
			log.error("支付异常", e);
		}
	}

	@Override
	public void notify(HttpServletRequest request) {
		try {
			verifyNotify(request);
		} catch (Exception e) {
			log.error("支付异常", e);
		}
	}

	/**
	 * 验证结果，执行支付回调
	 *
	 * @param request
	 * @throws Exception
	 */
	private void verifyNotify(HttpServletRequest request) throws Exception {

		String timestamp = request.getHeader("Wechatpay-Timestamp");
		String nonce = request.getHeader("Wechatpay-Nonce");
		String serialNo = request.getHeader("Wechatpay-Serial");
		String signature = request.getHeader("Wechatpay-Signature");

		log.info("timestamp:{} nonce:{} serialNo:{} signature:{}", timestamp, nonce, serialNo, signature);
		String result = HttpKit.readData(request);
		log.info("微信支付通知密文 {}", result);

		WechatPaymentSetting setting = wechatPaymentSetting();
		// 校验服务器端响应¬
		String plainText = WxPayKit.verifyNotify(serialNo, result, signature, nonce, timestamp, setting.getApiKey3(),
				Objects.requireNonNull(getPlatformCert()));

		log.info("微信支付通知明文 {}", plainText);

		JSONObject jsonObject = JSONUtil.parseObj(plainText);

		String payParamStr = jsonObject.getStr("attach");
		String payParamJson = URLDecoder.decode(payParamStr, StandardCharsets.UTF_8);
		PayParam payParam = JSONUtil.toBean(payParamJson, PayParam.class);

		String tradeNo = jsonObject.getStr("transaction_id");
		Double totalAmount = CurrencyUtil.reversalFen(jsonObject.getJSONObject("amount").getDouble("total"));

		PaymentSuccessParams paymentSuccessParams = new PaymentSuccessParams(PaymentMethodEnum.WECHAT.name(), tradeNo,
				totalAmount, payParam);

		paymentService.success(paymentSuccessParams);
		log.info("微信支付回调：支付成功{}", plainText);

		if (StringUtils.isNotEmpty(tradeNo)) {
			payCallBack(tradeNo);// 绑定推广人

			log.info("微信支付回调：支付成功,开始充值会员");
			LambdaQueryWrapper<Recharge> queryWrapper = new LambdaQueryWrapper<>();
			queryWrapper.eq(Recharge::getReceivableNo, tradeNo);
			// queryWrapper.in(Recharge::getRechargeType,"42","43","44","");
			Recharge one = rechargeService.getOne(queryWrapper);
			String owner = WalletOwnerEnum.RECHARGE.name();
			if (null != one && StrUtil.equalsAny(one.getRechargeType(), "42", "43", "44")) {// 这里 根据类型判断 支付类型
				PayParam payParams = new PayParam();
				payParams.setOwner(WalletOwnerEnum.RECHARGE.name());
				Recharge recharge = new Recharge();
				if ("42".equals(one.getRechargeType())) {
					recharge = rechargeService.rechargePartner(one.getRechargeMoney(), one.getPrice(), "2", owner,
							one.getMemberId(), one.getMemberName());
					payParams.setSn(recharge.getRechargeSn());
					payParams.setOwner("STORE_RECHARGE");
					payParams.setOrderType(CashierEnum.SELLER.name());
				} else if ("43".equals(one.getRechargeType()) || "44".equals(one.getRechargeType())) {
					recharge = rechargeService.rechargePartner(one.getRechargeMoney(), one.getPrice(), "3", owner,
							one.getMemberId(), one.getMemberName());
					payParams.setSn(recharge.getRechargeSn());
					payParams.setOwner("BUYER_RECHARGE");
					payParams.setOrderType(CashierEnum.MEMBER.name());
				}
				payParams.setClientType("WECHAT_MP");
				payParams.setMembeId(one.getMemberId());
				// 获取支付收银参数
				CashierParam cashierParam = cashierSupport.cashierParam(payParams);
				// this.rechargeCallBack(payParams,cashierParam,
				// one.getMemberId(),one.getMemberName());
				MemberWallet from = memberWalletService.getMemberWalletInfo(one.getMemberId(),
						WalletOwnerEnum.RECHARGE.name());
				Double price = cashierParam.getPrice();// 交易金额
				boolean b = memberWalletService.upgradHy(cashierParam.getOrderSns(), from, price);
				if (b) {
					Member member = memberMapper.selectById(one.getMemberId());
					recharge.setPayStatus(PayStatusEnum.PAID.name());
					rechargeService.updateById(recharge);
					updateMember(price, payParams.getOwner(), member.getId(), member.getUsername());
					log.info("微信支付回调：支付成功,充值会员成功！");
					// 在滚动消息里添加数据
					RollMessage rollMessage = new RollMessage();
					rollMessage.setContent(member.getNickName() + "成为会员");
					rollMessage.setCreateBy(member.getId());
					rollMessage.setCreateTime(new Date());
					rollMessage.setType(1);
					rollMessage.setStatus(1);
					rollMessage.setDelFlag(false);
					rollMessage.setId(String.valueOf(SnowFlake.getId()));
					boolean save = rollMessageMapper.insert(rollMessage) > 0;
					eextensionService.tempExToEx(one.getMemberId(), true);
					saveRechargeFow(recharge);
				} else {
					log.info("微信支付回调：充值会员失败！");
				}
			} else if (null != one && StrUtil.equalsAny(one.getRechargeType(), "45")) {
				// 充值合伙人
				PayParam payParams = new PayParam();
				Recharge recharge = rechargeService.rechargePartner(one.getRechargeMoney(), one.getPrice(), "5", owner,
						one.getMemberId(), one.getMemberName());
				payParams.setSn(recharge.getRechargeSn());
				payParams.setOwner(WalletOwnerEnum.RECHARGE.name());
				payParams.setOrderType(CashierEnum.DUES.name());
				payParams.setClientType("WECHAT_MP");
				payParams.setMembeId(one.getMemberId());
				// 获取支付收银参数
				CashierParam cashierParam = cashierSupport.cashierParam(payParams);
				MemberWallet from = memberWalletService.getMemberWalletInfo(one.getMemberId(),
						WalletOwnerEnum.RECHARGE.name());
				Double price = cashierParam.getPrice();// 交易金额
				boolean b = memberWalletService.upgradHhr(cashierParam.getOrderSns(), from, price);
				if (b) {
					Member member = memberMapper.selectById(one.getMemberId());
					recharge.setPayStatus(PayStatusEnum.PAID.name());
					rechargeService.updateById(recharge);
					updatePartner(payParams.getOrderType(), price, member.getId(), member.getUsername());

					log.info("微信支付回调：支付成功,合伙人缴费成功！");
				} else {
					log.info("微信支付回调：合伙人缴费失败！");
				}
			} else if (null != one && StrUtil.equalsAny(one.getRechargeType(), "6")) {
				// 消费
				PayParam payParams = new PayParam();
				payParams.setOwner(WalletOwnerEnum.RECHARGE.name());
				payParams.setSn(one.getOrderSn());
				payParams.setOrderType(CashierEnum.ORDER.name());
				payParams.setClientType("WECHAT_MP");
				payParams.setMembeId(one.getMemberId());
				// 获取支付收银参数
				// CashierParam cashierParam = cashierSupport.cashierParam(payParams);
				MemberWallet from = memberWalletService.getMemberWalletInfo(one.getMemberId(), payParams.getOwner());
				Member member = memberMapper.selectById(one.getMemberId());

				Order order = orderService.getOrderBySn(one.getOrderSn());
				Store store = storeService.getById(order.getStoreId());
				MemberWallet to = memberWalletService.getMemberWalletInfo(store.getMemberId(),
						WalletOwnerEnum.SALE.name());
				Double price = order.getGoodsPrice();// 商品价格
				Double colMoney = order.getFreightPrice();// 运费

				Double totalMoney = price + colMoney;
				if (NumberUtil.compare(from.getMemberWallet(), totalMoney) < 0) {
					throw new ServiceException(ResultCode.WALLET_INSUFFICIENT);
				}

				if (StringUtils.isNotEmpty(order.getConsigneeAddressIdPath())
						&& StringUtils.isEmpty(member.getLocation())) {
					String addressId = order.getConsigneeAddressIdPath()
							.substring(order.getConsigneeAddressIdPath().lastIndexOf(",") + 1);
					Region region = regionMapper.selectById(addressId);
					member.setLocation(region.getAdCode());
					memberMapper.updateById(member);
				}

				boolean flag = memberWalletService.payOrder(order.getSn(), from, to, price, colMoney, 0D);
				if (flag) {
					order.setFlowPrice(CurrencyUtil.add(order.getFlowPrice(),
							order.getCommission() != null ? order.getCommission() : 0D));
					// 下面是自提的信息，需要生成核销码，将核销码放到数据库中
					if ("SELF_PICK_UP".equals(order.getDeliveryMethod())) {
						order.setVerificationCode(orderService.getCode(order.getStoreId()));
						order.setDeliverStatus(DeliverStatusEnum.DELIVERED.name());
					}
					orderService.updateById(order);
					if (order.getOrderType() == "OFFLINE" || order.getOrderType().equals("OFFLINE")) {
						List<OrderItem> orderItems = new ArrayList<>();
						OrderItem orderItem = new OrderItem();
						orderItem.setOrderSn(order.getSn());// 线下sn
						orderItem.setTradeSn(order.getSn());
						orderItem.setGoodsPrice(order.getGoodsPrice());
						orderItem.setFlowPrice(order.getFlowPrice());// 焕呗总额
						// 有合同 并且 有折扣率
						if ("1".equals(store.getIsHaveContract()) && StringUtils.isNotEmpty(store.getDiscount())
								&& store.getDiscount() != "null") {
							// orderItem.setFee(Double.valueOf(SysDictUtils.getValueString("promote_withdrawal_rate",
							// "商家")));
							// 折现率
							orderItem.setFee(CurrencyUtil.div(Double.valueOf(store.getDiscount()), 100D));// 折现率
							orderItem.setDeposit(CurrencyUtil.mul(orderItem.getFlowPrice(), orderItem.getFee()));// 计算可提现金额
							orderItem.setSurplus(orderItem.getDeposit());// 剩余可提现金额
						} else {
							orderItem.setFee(0D);// 折现率
							orderItem.setDeposit(0D);// 计算可提现金额
							orderItem.setSurplus(0D);// 剩余可提现金额
						}
						orderItem.setRealization(0);
						orderItem.setSurplusPrice(order.getFlowPrice());
						orderItems.add(orderItem);
						orderItemService.saveBatch(orderItems);
					}
					paymentSuccessParams = new PaymentSuccessParams(PaymentMethodEnum.WALLET.name(), "", price,
							payParams);
					paymentService.success(paymentSuccessParams);
				}
				log.info("微信支付回调：支付成功,消费成功！");

			} else if (null != one && StrUtil.equalsAny(one.getRechargeType(), "46")) {
				// 扫码支付
				PayParam payParams = new PayParam();
				payParams.setOwner(WalletOwnerEnum.RECHARGE.name());
				payParams.setSn(one.getOrderSn());
				payParams.setOrderType(CashierEnum.ORDER.name());
				payParams.setClientType("WECHAT_MP");
				payParams.setMembeId(one.getMemberId());
				// 获取支付收银参数
				// CashierParam cashierParam = cashierSupport.cashierParam(payParams);
				MemberWallet from = memberWalletService.getMemberWalletInfo(one.getMemberId(), payParams.getOwner());
				Member member = memberMapper.selectById(one.getMemberId());

				Order order = orderService.getOrderBySn(one.getOrderSn());
				Store store = storeService.getById(order.getStoreId());
				order.setStoreName(store.getStoreName());
				String memberId = store.getMemberId();// 获取 店铺的 用户

				MemberWallet to = memberWalletService.getMemberWalletInfo(memberId, WalletOwnerEnum.SALE.name());
				Double totalMoney = order.getFlowPrice();
				if (NumberUtil.compare(from.getMemberWallet(), totalMoney) < 0) {
					throw new ServiceException(ResultCode.WALLET_INSUFFICIENT);
				}

				if (StringUtils.isNotEmpty(store.getStoreAddressIdPath())
						&& StringUtils.isEmpty(member.getLocation())) {
					String addressId = store.getStoreAddressIdPath()
							.substring(store.getStoreAddressIdPath().lastIndexOf(",") + 1);
					Region region = regionMapper.selectById(addressId);
					member.setLocation(region.getAdCode());
					memberMapper.updateById(member);
				}
				boolean flag = memberWalletService.scanPay(one.getOrderSn(), from, to, totalMoney, 0D);
				if (flag) {
					orderService.updateById(order);
					if (order.getOrderType() == "OFFLINE" || order.getOrderType().equals("OFFLINE")) {
						List<OrderItem> orderItems = new ArrayList<>();
						OrderItem orderItem = new OrderItem();
						orderItem.setOrderSn(order.getSn());// 线下sn
						orderItem.setTradeSn(order.getSn());
						orderItem.setGoodsPrice(order.getGoodsPrice());
						orderItem.setFlowPrice(order.getFlowPrice());// 焕呗总额
						// 有合同 并且 有折扣率
						if ("1".equals(store.getIsHaveContract()) && StringUtils.isNotEmpty(store.getDiscount())
								&& store.getDiscount() != "null") {
							// orderItem.setFee(Double.valueOf(SysDictUtils.getValueString("promote_withdrawal_rate",
							// "商家")));
							// 折现率
							orderItem.setFee(CurrencyUtil.div(Double.valueOf(store.getDiscount()), 100D));// 折现率
							orderItem.setDeposit(CurrencyUtil.mul(orderItem.getFlowPrice(), orderItem.getFee()));// 计算可提现金额
							orderItem.setSurplus(orderItem.getDeposit());// 剩余可提现金额
						} else {
							orderItem.setFee(0D);// 折现率
							orderItem.setDeposit(0D);// 计算可提现金额
							orderItem.setSurplus(0D);// 剩余可提现金额
						}
						orderItem.setRealization(0);
						orderItem.setSurplusPrice(order.getFlowPrice());
						orderItems.add(orderItem);
						orderItemService.saveBatch(orderItems);
					}
					paymentSuccessParams = new PaymentSuccessParams(PaymentMethodEnum.WALLET.name(), "", totalMoney,
							payParams);
					paymentService.success(paymentSuccessParams);
				}
				log.info("微信支付回调：支付成功,扫码支付成功！");
			}
		}
	}

	/**
	 * 获取区域代理商
	 *
	 * @param memberId
	 * @return
	 */
	public String getProxy(String memberId) {
		Member member = memberService.getById(memberId);
		if (ObjectUtil.isNotNull(member) && StrUtil.isNotEmpty(member.getLocation())) {
			String code = member.getLocation();
			String province = StrUtil.concat(true, StrUtil.subPre(code, 2), "0000");
			String city = StrUtil.concat(true, StrUtil.subPre(code, 4), "00");

			QueryWrapper<Partner> wrapper = new QueryWrapper<>();
			wrapper.eq("partner_type", "4");// 代理商
			wrapper.eq("delete_flag", 0);
			wrapper.eq("audit_state", "PASS");
			wrapper.in("region_id", province, city, code);
			wrapper.orderByDesc("region_id");
			wrapper.last("limit 1");
			Partner one = partnerService.getOne(wrapper);
			if (null != one) {
				return one.getMemberId();
			}
		}
		return null;
	}

	/**
	 * 充值会员成功，插入充值明细表
	 */
	public void saveRechargeFow(Recharge recharge) {
		RechargeFow rechargeFow = new RechargeFow();

		rechargeFow.setSn(recharge.getRechargeSn());
		Double ts = Double.valueOf(SysDictUtils.getValueString(DictCodeEnum.MEMBERSHIP_RATE.dictCode(), "天使合伙人"));

		String proxyUser = getProxy(recharge.getMemberId());
		if (StringUtils.isNotEmpty(proxyUser)) {
			rechargeFow.setMemberId(proxyUser);// 城市合伙人
			Double cs = Double.valueOf(SysDictUtils.getValueString(DictCodeEnum.APPORTION_FEE.dictCode(), "城市合伙人"));
			Double csFee = cs;
			// 查询上级推广人身份
			Member member = getExtMember(recharge.getMemberId());
			if (null != member) {
				QueryWrapper<Partner> query = new QueryWrapper<>();
				query.eq("member_id", member.getId());
				query.eq("partner_state", "0");
				query.eq("delete_flag", "0");
				query.last("limit 1");
				Partner partner = partnerService.getOne(query);
				// 推广人是天使
				if (partner != null && 2 == partner.getPartnerType()) {
					csFee = CurrencyUtil.mul(CurrencyUtil.sub(1D, ts), cs);
				} else {
					csFee = cs;
				}
			}
			rechargeFow.setHuanBei(CurrencyUtil.mul(recharge.getRechargeMoney(), csFee));
			rechargeFow.setCanHuanBei(CurrencyUtil.mul(recharge.getRechargeMoney(), csFee));
			rechargeFow.setAddTime(recharge.getCreateTime());
			rechargeFow.setRechargeType(recharge.getRechargeType());
			Double fee = 0D;
			// List<SysDictItemVO> allValue =
			// SysDictUtils.getAllValue(DictCodeEnum.MEMBERSHIP_PRICE.dictCode());
			// if (null != allValue) {
			// for (SysDictItemVO sysDictItemVO : allValue) {
			// Double val = Double.parseDouble(sysDictItemVO.getItemValue());
			// if (val.compareTo(recharge.getRechargeMoney()) == 0) {
			// fee =
			// Double.parseDouble(SysDictUtils.getValueString(DictCodeEnum.RECHARGE_RULE.dictCode(),
			// sysDictItemVO.getItemText()));
			// break;
			// }
			// }
			// }
			QueryWrapper<GradeVO> queryWrapper = Wrappers.query();
			queryWrapper.eq("mc.delete_flag", 0);
			queryWrapper.orderByDesc("mc.create_time");
			List<GradeVO> byMemberVO = gradeMapper.findByMemberVO(queryWrapper);
			if (null != byMemberVO) {
				for (GradeVO vo : byMemberVO) {
					Double val = vo.getMoney();
					if (val.compareTo(recharge.getRechargeMoney()) == 0) {
						fee = vo.getRechargeRule();
						break;
					}
				}
			}
			rechargeFow.setFee(fee);
			rechargeFow.setMoney(CurrencyUtil.mul(CurrencyUtil.mul(recharge.getRechargeMoney(), csFee), fee));
			rechargeFow.setCanMoney(CurrencyUtil.mul(CurrencyUtil.mul(recharge.getRechargeMoney(), csFee), fee));
			rechargeFow.setRealization("0");
			rechargeFowService.save(rechargeFow);
		}
	}

	/**
	 * 获取当前用户的推广人
	 * 
	 * @param memberId
	 * @return
	 */
	public Member getExtMember(String memberId) {
		QueryWrapper<Extension> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("member_id", memberId);
		queryWrapper.last("limit 1");
		Extension extension = eextensionService.getOne(queryWrapper);
		if (cn.hutool.core.util.ObjectUtil.isNotNull(extension)) {
			QueryWrapper<Member> queryWrapper1 = new QueryWrapper();
			queryWrapper1.eq("promotion_code", extension.getExtension());
			queryWrapper1.eq("delete_flag", "0");
			queryWrapper1.last("limit 1");
			Member member = memberService.getOne(queryWrapper1);
			if (ObjectUtil.isNotNull(member)) {
				log.info("用户{}绑定的推广码{},推广人为{}", memberId, extension.getExtension(), member.getId());
				return member;
			}

		}
		return null;
	}

	/**
	 * 支付成功后 回调绑定推广人
	 * 
	 * @param tradeNo
	 */
	private void payCallBack(String tradeNo) {
		LambdaQueryWrapper<Recharge> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(Recharge::getReceivableNo, tradeNo);
		Recharge one = rechargeService.getOne(queryWrapper);
		if (one != null) {
			eextensionService.tempExToEx(one.getMemberId(), true);
		}
	}

	// 修改合伙人信息
	void updatePartner(String orderType, Double price, String memberId, String memberName) {

		MemberVO member = memberService.getUserInfosByMemberId("BUYER", memberName);
		Partner partner = new Partner();
		QueryWrapper<Partner> wrapper = new QueryWrapper<>();
		wrapper.eq("member_id", memberId);
		// wrapper.eq("partner_type",member.getPartnerType());
		wrapper.eq("audit_state", PartnerStatusEnum.WAIT_SUBMIT.value());
		wrapper.eq("partner_state", 0);
		List<SysDictItemVO> allValue = SysDictUtils.getAllValue(DictCodeEnum.PARTNER_PRICE.dictCode());
		if (CollectionUtils.isNotEmpty(allValue)) {
			for (SysDictItemVO sysDictItemVO : allValue) {
				if (price.compareTo(Double.parseDouble(sysDictItemVO.getItemValue())) == 0) {
					QueryWrapper queryWrapper = new QueryWrapper();
					queryWrapper.eq("name", sysDictItemVO.getItemText());
					queryWrapper.eq("parent_id", 0);
					Role role = roleMapper.selectOne(queryWrapper);
					wrapper.eq("role_id", role != null ? role.getId() : null);
					break;
				}
			}
		}
		wrapper.orderByDesc("create_time");
		wrapper.last("limit 1");
		partner = partnerMapper.selectOne(wrapper);
		partner.setUpdateBy(memberId);
		partner.setUpdateTime(new Date());
		partner.setPayState(1);
		partner.setAuditState(PartnerStatusEnum.APPLYING.value());
		partnerMapper.updateById(partner);

		// 添加推广码
		Member member1 = new Member();
		member1.setId(member.getId());
		if (StringUtils.isEmpty(member.getPromotionCode())) {
			member1.setPromotionCode(eextensionService.getExtension());
		}
		memberMapper.updateById(member1);
	}

	// 修改会员信息
	void updateMember(Double price, String owner, String memberId, String memberName) {

		log.info("================================================开始修改会员信息");
		log.info("================================================金额：{},owner:{}", price, owner);
		MemberVO member = memberService.getUserInfosByMemberId("BUYER", memberName);
		log.info("================================================member：{}", member);
		if (member != null && member.getGradeId() != null) {
			QueryWrapper<GradeLevel> queryWrapper = new QueryWrapper<>();
			queryWrapper.eq("member_id", memberId);
			queryWrapper.eq("grade_id", member.getGradeId());
			queryWrapper.eq("grade_state", 0);
			if (owner.indexOf("STORE") != -1) {
				owner = "STORE";
				queryWrapper.like("owner", "STORE");
			} else if (owner.indexOf("BUYER") != -1) {
				owner = "BUYER";
				queryWrapper.like("owner", "BUYER");
			}
			queryWrapper.orderByDesc("end_time");
			queryWrapper.last("limit 1");
			GradeLevel gradeLevel = gradeLevelMapper.selectOne(queryWrapper);
			log.info("================================================gradeLevel：{}", gradeLevel);
			// 充值前先把原有的会员信息禁用
			gradeLevelMapper.updateByMemberId(memberId, owner);
			gradeLevel.setId(UUID.randomUUID().toString().replace("-", "").toLowerCase());
			gradeLevel.setGradeState(0);
			gradeLevel.setCreateBy(memberId);
			gradeLevel.setCreateTime(new Date());
			gradeLevel.setUpdateBy(null);
			gradeLevel.setUpdateTime(null);
			List<GradeVO> gradeVOS = gradeMapper.selectList(new QueryWrapper<>());
			if (CollectionUtils.isNotEmpty(gradeVOS)) {
				for (GradeVO grade : gradeVOS) {
					if (price.compareTo(grade.getMoney()) == 0) {
						gradeLevel.setGradeId(String.valueOf(grade.getId()));
					}
				}
			}
			gradeLevel.setOwner(owner);
			gradeLevelMapper.insert(gradeLevel);
			log.info("================================================修改成功11111");
		} else {
			GradeLevel gradeLevel = new GradeLevel();
			// 获取时间加一年或加一月或加一天
			Date date = new Date();
			Calendar cal = Calendar.getInstance();
			cal.setTime(date);// 设置起时间
			cal.add(Calendar.YEAR, 1);// 增加一年
			gradeLevel.setBeginTime(date);
			gradeLevel.setEndTime(cal.getTime());
			gradeLevel.setMemberId(memberId);
			gradeLevel.setGradeState(0);
			List<GradeVO> gradeVOS = gradeMapper.selectList(new QueryWrapper<>());
			if (CollectionUtils.isNotEmpty(gradeVOS)) {
				for (GradeVO grade : gradeVOS) {
					if (price.compareTo(grade.getMoney()) == 0) {
						gradeLevel.setGradeId(String.valueOf(grade.getId()));
					}
				}
			}
			if (owner.indexOf("STORE") != -1) {
				owner = "STORE";
			} else if (owner.indexOf("BUYER") != -1) {
				owner = "BUYER";
			}
			gradeLevel.setOwner(owner);
			gradeLevelMapper.insert(gradeLevel);
			log.info("================================================修改成功22222");
		}
		log.info("================================================修改会员信息结束");
	}

	// 修改商家会员信息
	void updateSeller(Double price, String owner, String memberId, String memberName) {

		MemberVO member = memberService.getUserInfosByMemberId("STORE", memberName);
		if (member != null && member.getGradeId() != null) {
			QueryWrapper<GradeLevel> queryWrapper = new QueryWrapper<>();
			queryWrapper.eq("member_id", memberId);
			queryWrapper.eq("grade_id", member.getGradeId());
			queryWrapper.eq("grade_state", 0);
			if (owner.indexOf("STORE") != -1) {
				owner = "STORE";
				queryWrapper.like("owner", "STORE");
			} else if (owner.indexOf("BUYER") != -1) {
				owner = "BUYER";
				queryWrapper.like("owner", "BUYER");
			}
			queryWrapper.orderByDesc("end_time");
			queryWrapper.last("limit 1");
			GradeLevel gradeLevel = gradeLevelMapper.selectOne(queryWrapper);
			// 充值前先把原有的会员信息禁用
			gradeLevelMapper.updateByMemberId(memberId, owner);
			gradeLevel.setId(UUID.randomUUID().toString().replace("-", "").toLowerCase());
			gradeLevel.setGradeState(0);
			gradeLevel.setCreateBy(memberId);
			gradeLevel.setCreateTime(new Date());
			gradeLevel.setUpdateBy(null);
			gradeLevel.setUpdateTime(null);
			GradeVO gradeVOS = gradeMapper.selectOne(new QueryWrapper<GradeVO>().eq("level", "9999"));
			if (gradeVOS != null) {
				gradeLevel.setGradeId(String.valueOf(gradeVOS.getId()));
			}
			StoreDetailVO storeDetail = storeDetailMapper.getStoreDetailByMemberId(memberId);
			Store store = new Store();
			store.setId(storeDetail.getStoreId());
			store.setMemberCreateTime(gradeLevel.getBeginTime());
			store.setMemberEndTime(gradeLevel.getEndTime());
			storeMapper.updateById(store);
			gradeLevel.setOwner(owner);
			gradeLevelMapper.insert(gradeLevel);
		} else {
			GradeLevel gradeLevel = new GradeLevel();
			// 获取时间加一年或加一月或加一天
			Date date = new Date();
			Calendar cal = Calendar.getInstance();
			cal.setTime(date);// 设置起时间
			cal.add(Calendar.YEAR, 1);// 增加一年
			gradeLevel.setBeginTime(date);
			gradeLevel.setEndTime(cal.getTime());
			gradeLevel.setMemberId(memberId);
			gradeLevel.setGradeState(0);
			gradeLevel.setCreateBy(memberId);
			gradeLevel.setCreateTime(new Date());
			GradeVO gradeVOS = gradeMapper.selectOne(new QueryWrapper<GradeVO>().eq("level", "9999"));
			if (gradeVOS != null) {
				gradeLevel.setGradeId(String.valueOf(gradeVOS.getId()));
			}
			StoreDetailVO storeDetail = storeDetailMapper.getStoreDetailByMemberId(memberId);
			Store store = new Store();
			store.setId(storeDetail.getStoreId());
			store.setMemberCreateTime(date);
			store.setMemberEndTime(cal.getTime());
			storeMapper.updateById(store);
			if (owner.indexOf("STORE") != -1) {
				owner = "STORE";
			} else if (owner.indexOf("BUYER") != -1) {
				owner = "BUYER";
			}
			gradeLevel.setOwner(owner);
			gradeLevelMapper.insert(gradeLevel);
		}
	}

	@Override
	public void refund(RefundLog refundLog) {

		try {

			Amount amount = new Amount().setRefund(CurrencyUtil.fen(refundLog.getTotalAmount()))
					.setTotal(CurrencyUtil.fen(orderService.getPaymentTotal(refundLog.getOrderSn())));

			// 退款参数准备
			RefundModel refundModel = new RefundModel().setTransaction_id(refundLog.getPaymentReceivableNo())
					.setOut_refund_no(refundLog.getOutOrderNo()).setReason(refundLog.getRefundReason())
					.setAmount(amount)
					.setNotify_url(refundNotifyUrl(apiProperties.getBuyer(), PaymentMethodEnum.WECHAT));

			WechatPaymentSetting setting = wechatPaymentSetting();

			log.info("微信退款参数 {}", JSONUtil.toJsonStr(refundModel));
			PaymentHttpResponse response = WechatApi.v3(RequestMethodEnums.POST, WechatDomain.CHINA.toString(),
					WechatApiEnum.DOMESTIC_REFUNDS.toString(), setting.getMchId(), setting.getSerialNumber(), null,
					setting.getApiclient_key(), JSONUtil.toJsonStr(refundModel));
			log.info("微信退款响应 {}", response);
			// 退款申请成功
			if (response.getStatus() == 200) {
				refundLogService.save(refundLog);
			} else {
				// 退款申请失败
				refundLog.setErrorMessage(response.getBody());
				refundLogService.save(refundLog);
			}
		} catch (Exception e) {
			log.error("微信退款申请失败", e);
		}

	}

	@Override
	public void cancel(RefundLog refundLog) {
		this.refund(refundLog);
	}

	@Override
	public void refundNotify(HttpServletRequest request) {
		String timestamp = request.getHeader("Wechatpay-Timestamp");
		String nonce = request.getHeader("Wechatpay-Nonce");
		String serialNo = request.getHeader("Wechatpay-Serial");
		String signature = request.getHeader("Wechatpay-Signature");

		log.info("timestamp:{} nonce:{} serialNo:{} signature:{}", timestamp, nonce, serialNo, signature);
		String result = HttpKit.readData(request);
		log.info("微信退款通知密文 {}", result);
		JSONObject ciphertext = JSONUtil.parseObj(result);

		try { // 校验服务器端响应¬
			String plainText = WxPayKit.verifyNotify(serialNo, result, signature, nonce, timestamp,
					wechatPaymentSetting().getApiKey3(), Objects.requireNonNull(getPlatformCert()));
			log.info("微信退款通知明文 {}", plainText);

			if (("REFUND.SUCCESS").equals(ciphertext.getStr("event_type"))) {
				log.info("退款成功 {}", plainText);
				// 校验服务器端响应
				JSONObject jsonObject = JSONUtil.parseObj(plainText);
				String transactionId = jsonObject.getStr("transaction_id");
				String refundId = jsonObject.getStr("refund_id");

				RefundLog refundLog = refundLogService.getOne(
						new LambdaQueryWrapper<RefundLog>().eq(RefundLog::getPaymentReceivableNo, transactionId));
				if (refundLog != null) {
					refundLog.setIsRefund(true);
					refundLog.setReceivableNo(refundId);
					refundLogService.saveOrUpdate(refundLog);
				}

			} else {
				log.info("退款失败 {}", plainText);
				JSONObject jsonObject = JSONUtil.parseObj(plainText);
				String transactionId = jsonObject.getStr("transaction_id");
				String refundId = jsonObject.getStr("refund_id");

				RefundLog refundLog = refundLogService.getOne(
						new LambdaQueryWrapper<RefundLog>().eq(RefundLog::getPaymentReceivableNo, transactionId));
				if (refundLog != null) {
					refundLog.setReceivableNo(refundId);
					refundLog.setErrorMessage(ciphertext.getStr("summary"));
					refundLogService.saveOrUpdate(refundLog);
				}
			}
		} catch (Exception e) {
			log.error("微信退款失败", e);
		}
	}

	/**
	 * 获取微信支付配置
	 *
	 * @return
	 */
	private WechatPaymentSetting wechatPaymentSetting() {
		try {
			Setting systemSetting = settingService.get(SettingEnum.WECHAT_PAYMENT.name());
			WechatPaymentSetting wechatPaymentSetting = JSONUtil.toBean(systemSetting.getSettingValue(),
					WechatPaymentSetting.class);
			return wechatPaymentSetting;
		} catch (Exception e) {
			log.error("微信支付暂不支持", e);
			throw new ServiceException(ResultCode.PAY_NOT_SUPPORT);
		}
	}

	/**
	 * 获取平台公钥
	 *
	 * @return 平台公钥
	 */
	private X509Certificate getPlatformCert() {
		// 获取缓存中的平台公钥，如果有则直接返回，否则去微信请求
		String publicCert = cache.getString(CachePrefix.WECHAT_PLAT_FORM_CERT.getPrefix());
		if (!StringUtils.isEmpty(publicCert)) {
			return PayKit.getCertificate(publicCert);
		}
		// 获取平台证书列表
		try {

			WechatPaymentSetting setting = wechatPaymentSetting();

			PaymentHttpResponse response = WechatApi.v3(RequestMethodEnums.GET, WechatDomain.CHINA.toString(),
					WechatApiEnum.GET_CERTIFICATES.toString(), setting.getMchId(), setting.getSerialNumber(), null,
					setting.getApiclient_key(), "");
			String body = response.getBody();
			log.info("获取微信平台证书body: {}", body);
			if (response.getStatus() == 200) {
				JSONObject jsonObject = JSONUtil.parseObj(body);
				JSONArray dataArray = jsonObject.getJSONArray("data");
				// 默认认为只有一个平台证书
				JSONObject encryptObject = dataArray.getJSONObject(0);
				JSONObject encryptCertificate = encryptObject.getJSONObject("encrypt_certificate");
				String associatedData = encryptCertificate.getStr("associated_data");
				String cipherText = encryptCertificate.getStr("ciphertext");
				String nonce = encryptCertificate.getStr("nonce");
				publicCert = getPlatformCertStr(associatedData, nonce, cipherText);
				long second = (PayKit.getCertificate(publicCert).getNotAfter().getTime() - System.currentTimeMillis())
						/ 1000;
				cache.put(CachePrefix.WECHAT_PLAT_FORM_CERT.getPrefix(), publicCert, second);
			} else {
				log.error("证书获取失败：{}" + body);
				throw new ServiceException(ResultCode.WECHAT_CERT_ERROR);
			}
			return PayKit.getCertificate(publicCert);
		} catch (Exception e) {
			log.error("证书获取失败", e);
		}
		return null;
	}

	/**
	 * 获取平台证书缓存的字符串 下列各个密钥参数
	 *
	 * @param associatedData
	 *            密钥参数
	 * @param nonce
	 *            密钥参数
	 * @param cipherText
	 *            密钥参数
	 * @return platform key
	 * @throws GeneralSecurityException
	 *             密钥获取异常
	 */
	private String getPlatformCertStr(String associatedData, String nonce, String cipherText)
			throws GeneralSecurityException {

		AesUtil aesUtil = new AesUtil(wechatPaymentSetting().getApiKey3().getBytes(StandardCharsets.UTF_8));
		// 平台证书密文解密
		// encrypt_certificate 中的 associated_data nonce ciphertext
		return aesUtil.decryptToString(associatedData.getBytes(StandardCharsets.UTF_8),
				nonce.getBytes(StandardCharsets.UTF_8), cipherText);
	}
}
